#include <vector>
#include <iostream>
#include <functional>
#include <unordered_map>
#include <memory>
#include <unistd.h>

using std::vector;
using std::cout;
using std::endl;
using TaskFunc = std::function<void()>;

class TimerTask
{
    using ReleaseFunc = std::function<void()>;
private:
    uint64_t _id;
    int _timeout;
    bool _is_cancel;
    TaskFunc _func_cb;
    ReleaseFunc _release;   //倒逼使用者传参
public:
    TimerTask(uint64_t id, int timeout, TaskFunc func_cb, ReleaseFunc release)
    :_id(id), _timeout(timeout), _func_cb(func_cb), _release(release),_is_cancel(false)
    {

    }

    ~TimerTask()
    {
        if(!_is_cancel)
            _func_cb();
        _release();
    }

    int GetTimeout()
    {
        return _timeout;
    }

    void Cancel()
    {
        _is_cancel = true;
    }
    // void SetRelease(ReleaseFunc& release)
    // {
    //     _release = release;
    // }
};


class TimerWheel
{
    using PtrTask = std::shared_ptr<TimerTask>;
    using WeakPtr = std::weak_ptr<TimerTask>;
private:
    int _capacity;
    int _tick;      //_tick的值即为“当前时刻”
    vector<vector<PtrTask>> _wheels;
    std::unordered_map<uint64_t, WeakPtr>  _timers;     //主要用于索引
    
private:
    void RemoveTimer(uint64_t id)      //本质从索引中删除，绑定给TimeTask，在TimeTask的析构中统一执行！
    {
        auto it = _timers.find(id);
        if(it != _timers.end())
        {
            _timers.erase(it);
        }
    }
    
public:

    TimerWheel(int capacity = 60)
    :_capacity(capacity), _tick(0),_wheels(_capacity)
    {

    }

    ~TimerWheel()
    {

    }

    void TimerAdd(uint64_t id, int timeout, const TaskFunc& func_cb)    //bind之后相当于不需要参数了
    {
        PtrTask pt (new TimerTask(id,timeout,func_cb, std::bind(&TimerWheel::RemoveTimer,this,id)));    //注意bind成员函数时的写法
        _wheels[timeout].push_back(pt);
        _timers[id] = WeakPtr(pt);
    }
 
    //刷新给定的id的任务的超时时间
    void TimerRefresh(uint64_t id)
    {
        //1. 取出任务对应的shared_ptr
        auto it = _timers.find(id);
        if(it == _timers.end())
        {
            return;
        }
        PtrTask pt = it->second.lock();

        //2. 添加至时间轮中     只有在时间轮中的位置变了，id和回调都不变
        _wheels[(_tick + pt->GetTimeout()) % _capacity].push_back(pt); 
    }

    //每个单位时间执行一次
    void TimerRun()
    {
        _tick = (_tick + 1) % _capacity;

        //直接释放对应单位时间上的对象，相当于“自动执行回调”（调用析构）
        _wheels[_tick].clear();
    }

    //取消给定的id的定时任务
    void TimerCancel(uint64_t id)
    {
        auto it = _timers.find(id);
        if(it == _timers.end())
        {
            return;
        }
        PtrTask pt = it->second.lock();     //不能直接RemoveTimer原因：RemoveTimer的本质作用在索引上
        pt->Cancel();
    }
};


class Test
{
public:
    Test(){cout << "task construct !!!" << endl;}
    ~Test(){cout << "task destruct !!!" << endl;}
};


void Test()
{
    cout << "debug..." << endl;
}


int main()
{
    TimerWheel tw;
    tw.TimerAdd(1,5,Test);

    int cnt = 0;
    while(1)
    {
        if(cnt == 3)
        {
            cout << "Task 1 has been refreshed !" << endl;
            tw.TimerRefresh(1);
            tw.TimerCancel(1);
        }
        cout << cnt << "--timer is running..." << endl;
        tw.TimerRun();
        cnt++;
        sleep(1);
    }

    return 0;
}